package com.entity;

import java.io.*;

import javax.servlet.http.HttpServletResponse;

import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.DownloadCallback;
import org.csource.fastdfs.FileInfo;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.csource.fastdfs.UploadCallback;

/**
 * @ClassName: FastDfsUtil
 * 
 * @Description: FastDfs文件管理简单工具类
 * 
 * @version V1.0
 * 
 */

public class FastDfsApi {

	// private static Logger logger = LoggerFactory.getLogger(FastDfsApi.class);

	static FastDfsApi fdfs = null;
	private StorageClient storageClient = null;
	// 5.声明一个StorageServer
	StorageServer storageServer = null;
	TrackerServer trackerServer = null;
	protected final String def_extname = "zdy";

	private FastDfsApi() {
	}

	public static FastDfsApi getInstance() {
		if (fdfs == null) {
			fdfs = new FastDfsApi();
			fdfs.ini();
		}
		return fdfs;
	}

	/**
	 * 初始化 载入配置
	 */
	public void ini() {

		// 加载原 conf 格式文件配置：
		try {
			ClientGlobal.init("fdfs_client.conf");
			// 3.创建一个TrackerClient对象
			TrackerClient trackerClient = new TrackerClient();
			// 4.创建一个TrakerServer对象
			trackerServer = trackerClient.getConnection();

			// 6.获取StorageClient对象
			storageClient = new StorageClient(trackerServer, storageServer);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// ClientGlobal.init("config/fdfs_client.conf");
		// ClientGlobal.init("/opt/fdfs_client.conf");
		// ClientGlobal.init("C:\\Users\\James\\config\\fdfs_client.conf");
	}

	public void close() {
		try {
			if (storageServer != null)
				storageServer.close();
			if (trackerServer != null)
				trackerServer.close();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * @Title: upload
	 * 
	 * @Description: 通过文件流上传文件
	 * 
	 * @param @param inputStream 文件流
	 * 
	 * @param @param filename 文件名称
	 * 
	 * @param @return
	 * 
	 * @param @throws IOException
	 * 
	 * @param @throws MyException
	 * 
	 * @return String 返回文件在FastDfs的存储路径
	 * 
	 * @throws
	 * 
	 */

	public String[] upload(byte[] bytes, String filename) throws IOException, MyException {

		String suffix = ""; // 后缀名

		try {
			suffix = filename.substring(filename.lastIndexOf(".") + 1);
		} catch (Exception e) {
			suffix = def_extname;
		}

		NameValuePair[] meta_list = new NameValuePair[3];
		meta_list[0] = new NameValuePair("fileName", filename);
		meta_list[1] = new NameValuePair("fileExt", suffix);
		meta_list[2] = new NameValuePair("fileSize", String.valueOf(bytes.length));

		String[] strings = storageClient.upload_file(bytes, suffix, meta_list); // 上传文件
		return strings;

	}

	/**
	 * @Title: fdfsUpload
	 * 
	 * @Description: 本地文件上传
	 * 
	 * @param @param filepath 本地文件路径
	 * 
	 * @param @return
	 * 
	 * @param @throws IOException
	 * 
	 * @param @throws MyException
	 * 
	 * @return String 返回文件在FastDfs的存储路径
	 * 
	 * @throws
	 * 
	 */

	public String[] upload(String filepath) throws IOException, MyException {

		String suffix = ""; // 后缀名

		try {
			suffix = filepath.substring(filepath.lastIndexOf(".") + 1);
		} catch (Exception e) {
			suffix = def_extname;
		}

		String[] strings = storageClient.upload_file(filepath, suffix, null); // 上传文件
		return strings;

	}

	public String[] upload(InputStream inStream, String uploadFileName, long fileLength) throws IOException {

		String[] results = null;
		String fileExtName = "";
		if (uploadFileName.contains(".")) {
			fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
		} else {
			fileExtName = def_extname;
		}

		NameValuePair[] metaList = new NameValuePair[3];
		metaList[0] = new NameValuePair("fileName", uploadFileName);
		metaList[1] = new NameValuePair("fileExt", fileExtName);
		metaList[2] = new NameValuePair("fileSize", String.valueOf(fileLength));

		UploadCallback callback = new UpCallback(inStream);
		//inStream.close();
		try {
			results = storageClient.upload_file(null, fileLength, callback, fileExtName, metaList);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return results;

	}

	/**
	 * @Title: download
	 * 
	 * @Description: 下载文件到目录
	 * 
	 * @param @param savepath 文件存储路径
	 * 
	 * @param @param localPath 下载目录
	 * 
	 * @param @return
	 * 
	 * @param @throws IOException
	 * 
	 * @param @throws MyException
	 * 
	 * @return boolean 返回是否下载成功
	 * 
	 * @throws
	 * 
	 */

	public boolean download(String savepath, String localPath) throws IOException, MyException {

		String group = ""; // 存储组

		String path = ""; // 存储路径

		try {

			int secondindex = savepath.indexOf("/", 2); // 第二个"/"索引位置

			group = savepath.substring(1, secondindex); // 类似：group1

			path = savepath.substring(secondindex + 1); // 类似：M00/00/00/wKgBaFv9Ad-Abep_AAUtbU7xcws013.png

		} catch (Exception e) {

			throw new RuntimeException("传入文件存储路径不正确!格式例如：/group1/M00/00/00/wKgBaFv9Ad-Abep_AAUtbU7xcws013.png");

		}

		int result = storageClient.download_file(group, path, localPath);

		if (result != 0) {
			throw new RuntimeException("下载文件失败：文件路径不对或者文件已删除!");
		}

		return true;

	}

	/**
	 * @Title: download
	 * 
	 * @Description: 返回文件字符数组
	 * 
	 * @param @param savepath 文件存储路径
	 * 
	 * @param @return
	 * 
	 * @param @throws IOException
	 * 
	 * @param @throws MyException
	 * 
	 * @return byte[] 字符数组
	 * 
	 * @throws
	 * 
	 */

	public byte[] download(String savepath) throws IOException, MyException {

		byte[] bs = null;

		String group = ""; // 存储组

		String path = ""; // 存储路径

		try {

			int secondindex = savepath.indexOf("/", 2); // 第二个"/"索引位置

			group = savepath.substring(1, secondindex); // 类似：group1

			path = savepath.substring(secondindex + 1); // 类似：M00/00/00/wKgBaFv9Ad-Abep_AAUtbU7xcws013.png

		} catch (Exception e) {

			throw new RuntimeException("传入文件存储路径不正确!格式例如：/group1/M00/00/00/wKgBaFv9Ad-Abep_AAUtbU7xcws013.png");

		}

		bs = storageClient.download_file(group, path); // 返回byte数组

		return bs;

	}

	/**
	 * 分段下载
	 * 
	 * @param savepath
	 * @param file_offset
	 * @param download_bytes
	 * @param callback
	 */
	public void download(String savepath, long file_offset, long download_bytes, DownloadCallback callback) {
		String group = ""; // 存储组

		String path = ""; // 存储路径

		int secondindex = savepath.indexOf("/", 2); // 第二个"/"索引位置

		group = savepath.substring(1, secondindex); // 类似：group1

		path = savepath.substring(secondindex + 1); // 类似：M00/00/00/wKgBaFv9Ad-Abep_AAUtbU7xcws013.png
		try {
		//	System.out.println("group="+group);
		//	System.out.println("path="+path);
		//	System.out.println("file_offset="+file_offset);
		//	System.out.println("download_bytes="+download_bytes);
			storageClient.download_file(group, path, file_offset, download_bytes, callback);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * @Title: delete
	 * 
	 * @Description: 删除文件
	 * 
	 * @param @param savepath 文件存储路径
	 * 
	 * @param @return
	 * 
	 * @param @throws IOException
	 * 
	 * @param @throws MyException
	 * 
	 * @return boolean 返回true表示删除成功
	 * 
	 * @throws
	 * 
	 */

	public boolean delete(String savepath) throws IOException, MyException {

		String group = ""; // 存储组

		String path = ""; // 存储路径

		try {

			int secondindex = savepath.indexOf("/", 2); // 第二个"/"索引位置

			group = savepath.substring(1, secondindex); // 类似：group1

			path = savepath.substring(secondindex + 1); // 类似：M00/00/00/wKgBaFv9Ad-Abep_AAUtbU7xcws013.png

		} catch (Exception e) {

			throw new RuntimeException("传入文件存储路径不正确!格式例如：/group1/M00/00/00/wKgBaFv9Ad-Abep_AAUtbU7xcws013.png");

		}

		int result = storageClient.delete_file(group, path); // 删除文件，0表示删除成功

		if (result != 0) {

			throw new RuntimeException("删除文件失败：文件路径不对或者文件已删除!");

		}

		return true;

	}

	/**
	 *
	 * 
	 * @Title: fdfdFileInfo
	 * 
	 * @Description: 返回文件信息
	 * 
	 * @param @param savepath 文件存储路径
	 * 
	 * @param @return
	 * 
	 * @param @throws IOException
	 * 
	 * @param @throws MyException
	 * 
	 * @return FileInfo 文件信息
	 * 
	 * @throws
	 * 
	 */

	public FileInfo getFileInfo(String savepath) throws IOException, MyException {

		String group = ""; // 存储组

		String path = ""; // 存储路径

		try {

			int secondindex = savepath.indexOf("/", 2); // 第二个"/"索引位置

			group = savepath.substring(1, secondindex); // 类似：group1

			path = savepath.substring(secondindex + 1); // 类似：M00/00/00/wKgBaFv9Ad-Abep_AAUtbU7xcws013.png

		} catch (Exception e) {

			// ("传入文件存储路径不正确!格式例如：/group1/M00/00/00/wKgBaFv9Ad-Abep_AAUtbU7xcws013.png");
			return null;
		}

		FileInfo fileInfo = storageClient.get_file_info(group, path);

		return fileInfo;

	}

	
}
class UpCallback implements UploadCallback {

	private InputStream inStream;

	public UpCallback(InputStream inStream) {
		this.inStream = inStream;
	}

	public int send(OutputStream out) throws IOException {

		byte[] buffer = new byte[2048];
		int length = -1;
		while ((length = inStream.read(buffer)) != -1) {
			out.write(buffer, 0, length);
		}
		out.flush();
		//inStream.close();
		//out.close();
		return 0;
	}

}
/**
 * 分布式文件采用异步方式调取 下载
 *
 */
class DownCallback implements DownloadCallback {
	public OutputStream os = null;

	public DownCallback(HttpServletResponse res) {
		try {
			os = res.getOutputStream();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}

	@Override
	public int recv(long file_size, byte[] data, int bytes) {
		try {
			//System.out.println("bytes"+bytes);
			os.write(data,0,bytes);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return 0;
	}
}
